package Domaine;

import java.awt.Point;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import Domaine.Urgence;
import Domaine.Urgence.EtatUrgence;
import Erreurs.*;

/**
 * 
 * @author Noyau
 * @version 1.0
 * @since 2013-11-12
 * File Segment.java
 *
 */
public class Noeud implements Cloneable
{
	//Attributs
	private Point _coordonnee; 			//emplacement du Noeud sur la carte
	private ArrayList<Urgence> _listeUrgences;		//La liste des urgences affect�es au noeud			

	//M�thodes publiques
	
	public Noeud(Point c)
	{
		this._listeUrgences = new ArrayList<Urgence>();
		this._coordonnee = c;
	}
	
	public Noeud(int x, int y){
		this._listeUrgences = new ArrayList<Urgence>();
		this._coordonnee = new Point(x,y);
	}
	
	public Noeud clone() 
	{
		Noeud copy = null;
		try
		{
			copy = (Noeud) super.clone();
		} catch(CloneNotSupportedException copyExcept)
		{
			copyExcept.printStackTrace(System.err);
		}
	
		if (_listeUrgences == null)
		{
			copy._listeUrgences = null;
		}
		else
		{
			copy._listeUrgences = new ArrayList<Urgence>();
			for(Urgence urgence: _listeUrgences) copy._listeUrgences.add(urgence.clone());
		}
		
		return copy;
	}
	
	/**
	 * 
	 * @return Coordonnee Les coordonn�es du noeud
	 */
	public Point getCoordonee() 
	{
		return this._coordonnee;
	}
	
	/**
	 * 
	 * @return float : La coordonn�e X du noeud
	 */
	public int getX() 
	{
		return (int) this._coordonnee.getX();
	}
	
	/**
	 * 
	 * @return float : La coordonn�e Y du noeud
	 */
	public int getY() 
	{
		return (int) this._coordonnee.getY();
	}

	/**
	 * 
	 * @param aCoord : La coordonn�e du noeud
	 */
	public void setCoordonnee(Point p) 
	{
		this._coordonnee = p;
	}


	public List<Urgence> getListeUrgences() {
		return this._listeUrgences;
	}
	
	
	/**
	 * 
	 * @param urgence : L'urgence a retirer de la liste
	 */
	public void supprimerUrgence(Urgence urgence) throws ObjetInexistantError
	{
		if (!(_listeUrgences.contains(urgence)))
		{
			throw new ObjetInexistantError("L'urgence est inexistante dans la liste des urgences");
		}
		
		_listeUrgences.remove(urgence);
	}
	
	static public float calculerDistanceEntreDeuxNoeuds(Noeud _noeudDepart, Noeud _noeudFin)
	{
		return (float) Math.sqrt(Math.pow(Math.abs(_noeudDepart.getX() - _noeudFin.getX()),2.0f) + Math.pow(Math.abs(_noeudDepart.getY() - _noeudFin.getY()),2.0f));
	}
	

	static public float calculerDistanceEntreDeuxPoints(Point a, Point b)
	{
		return (float) Math.sqrt(Math.pow(Math.abs(b.getX() - a.getX()),2.0f) + Math.pow(Math.abs(b.getY() - a.getY()),2.0f));		
	}
	
	static public Point obtenirCoordonneeDistance(Point vehicule, Noeud fin, double d) {
		
		int deltaY = fin.getY() - vehicule.y;
		int deltaX = fin.getX() - vehicule.x;

		double t = Math.toDegrees( Math.atan2( deltaY, deltaX ) );
		int bx;
		int by;
		
		if (vehicule.y > fin.getY())
		{
			by = vehicule.y - (int) Math.abs(d*Math.sin(Math.toRadians(t)));
		}
		else
		{	
			by = vehicule.y + (int) Math.abs(d*Math.sin(Math.toRadians(t)));
		}
		
		if (vehicule.x > fin.getX())
		{
			bx = vehicule.x - (int) Math.abs(d*Math.cos(Math.toRadians(t)));
		}
		else
		{	
			bx = vehicule.x + (int) Math.abs(d*Math.cos(Math.toRadians(t)));
		}
		
		return new Point(bx,  by);
		
	}
	
	/**
	 * 
	 * @param urgence : L'urgence a ajouter de la liste
	 */
	
	public void ajouterUrgence(Urgence urgence) throws ObjetExistantError
	{
		if ((_listeUrgences.contains(urgence)))
		{
			throw new ObjetExistantError("Le segment est existant dans la liste des segments");
		}
		
		_listeUrgences.add(urgence);
		//urgence.setNoeud(this); 
	}
	
	
	@Override
	public boolean equals(Object obj){
		
		boolean b = false;
		if(obj instanceof Noeud){
			Noeud n = (Noeud) obj;
			if(this._coordonnee.getX() == n.getX() && this._coordonnee.getY() == n.getY()){
				b = true;
			}
		}
		return b;
	}
	
	
	public boolean possedeUrgenceActive() 
	{
		
		for (Urgence urgence : _listeUrgences)
		{
			Date _dateCreation = new Date();
			
			if (urgence == null)
			{
				return false;
			}
			
			if (urgence.getDateDeclenchement().compareTo(_dateCreation) == -1 && urgence.getEtat() == EtatUrgence.EnDiffere)
			{
				urgence.setEtat(EtatUrgence.EnAttente);
			}
			
			if (urgence.getEtat() == EtatUrgence.EnAttente)  
			{
				return true;
			}
			
		}
		return false;
	}
	
}